#include <gba.h>


#include "data/enterprise.h"
#include "data/background.h"
#include "data/platform.h"
#include "data/crashprice.h"
#include "data/gas.h"
#include "data/bar.h"



#define TOP_LEFT   			0
#define TOP_MIDDLE 			1
#define TOP_RIGHT  			2
#define MIDDLE_LEFT			3
#define MIDDLE				4
#define MIDDLE_RIGHT		5
#define BOTTOM_LEFT			6
#define BOTTOM_MIDDLE		7
#define BOTTOM_RIGHT		8

#define DIRECTION_LEFT		9
#define DIRECTION_RIGHT		10

#define STATE_WON			11
#define STATE_LOST			12
#define STATE_START			13
#define STATE_STOPPED		14
#define STATE_TANK_EMPTY	15



/*
backgroudnd und enterprise erstellt mir pcx2gba.exe
TXT4 
- Outputs image in 16bit values (2 pixels per value), and palette in 16bit values into an array in a C header file
- Used with GBA Mode 4
- 8Bit PCX Images Only

USAGE:
pcx2gba.exe mode image outfile [name]
pcx2gba.exe TXT4 background.pcx background.h background
*/

#define OAM_Mem		((u16*)0x7000000) // Sprites(128), coordinates, size..(total 1Kb)
#define A        2

struct collissionpoints
{
	int x;
	int y;
};

struct collissionpoints cp []={
								{ 0,  0}, {16, 0}, {32, 0},
								{ 0, 16}, {16,16}, {32,16},
								{ 0, 32}, {16,32}, {32,32}
							   };

void CopyOAM(void);
void waitForVblank(void);
void MoveEnterprise(OAMEntry* sprite, int x, int y);
void MovePlatform(OAMEntry* sprite, int x, int y);
void PositionCaulate(void);
void BorderDetection(void);
void CollissionDetection(int ShipPositionX, int ShipPositionY, int PlatformPositionX, int PlatformPositionY);


OAMEntry sprites[128];
int shipPositionX = 2000;
int shipPositionY = 2000;
int shipVx=0;
int shipVy=0;
int shipThrustX=0;
int shipThrustY=0;
int dv=0;

int shipGas = 0;


//platform specific variables
int platformPositionX = 100;
int platformPositionY = 94;
int direction = DIRECTION_RIGHT;

//information specigic variables
int wonX = 40;
int wonY = 40;

//state specific variables

int currentState = STATE_START;


int main()
{
	int i;
   	SetMode(MODE_4 | BG2_ENABLE | OBJ_ENABLE | OBJ_MAP_1D);
	
	for(i = 0; i < 256; i++) 
	{
		OBJPaletteMem[i] = enterprisepal[i];
	}

	for (i = 0; i < 256; i++) 
	{
		BGPaletteMem[i]=backgroundpal[i];

		
	}

	for (i = 0; i < (120*160); i++) 
	{
		FrontBuffer[i] =backgrounddata[i] ;
		
	}


	
	memcpy( (u16 *)0x06014000, &enterprisedata, sizeof(enterprisedata) );
	sprites[0].attribute[0] = COLOR_256 | SQUARE | (shipPositionX/100);
	sprites[0].attribute[1] = SIZE_32;
	sprites[0].attribute[2] = 512;
	
		
	memcpy( (u16 *)0x06014400, &platformdata, sizeof(platformdata) );
	sprites[1].attribute[0] = COLOR_256 | TALL | platformPositionY;
	sprites[1].attribute[1] = SIZE_64 | platformPositionX;
	sprites[1].attribute[2] = 512+32;
	
	memcpy( (u16 *)0x06014C00, &bardata, sizeof(bardata) );
	sprites[2].attribute[0] = COLOR_256 | TALL | 0;
	sprites[2].attribute[1] = SIZE_8 | 100;
	sprites[2].attribute[2] = 512+32+64;

	//DrawLandscape();
	while(1)
	{
	
	
	
	waitForVblank();
	shipThrustX=0;
	shipThrustY=0;
	
	if(currentState != STATE_TANK_EMPTY)
	{
		if(!(REG_KEYS & KEY_UP))
		{

			shipThrustY=3;
			++shipGas;
					

		}
		if(!(REG_KEYS & KEY_LEFT))
		{
			shipThrustX=-3;
			++shipGas;
					

		}
		if(!(REG_KEYS & KEY_RIGHT))
		{
			shipThrustX=3;
			++shipGas;
				

		}
	}
		
		if(direction == DIRECTION_LEFT)
		{
			platformPositionX-=1;
		}
		else if(direction == DIRECTION_RIGHT)
		{	
			platformPositionX+=1;
		}
		if(platformPositionX==1)
		{
			direction = DIRECTION_RIGHT;
		}
		if(platformPositionX==240-32)
		{
			direction = DIRECTION_LEFT;
		}
		
	PositionCalculate();
	BorderDetection();
	CollissionDetection(shipPositionX, shipPositionY, platformPositionX, platformPositionY);
	checkGas();
	if(currentState != STATE_LOST && currentState != STATE_WON)
	{
	MoveEnterprise(&sprites[0],shipPositionX,shipPositionY);
	MovePlatform(&sprites[1],platformPositionX, platformPositionY);
	MoveGas(&sprites[2]);
	}


	CopyOAM();
	}

	
  return 0;
}


void waitForVblank(void)
{
  while(! (REG_DISPSTAT & DISPSTAT_VB));
  while(REG_DISPSTAT & DISPSTAT_VB);

}

void MoveEnterprise(OAMEntry* sprite, int x, int y)
{
	sprite->attribute[1] = sprite->attribute[1] & 0xFE00;
	sprite->attribute[1] = sprite->attribute[1] | (x/100);

	sprite->attribute[0] = sprite->attribute[0] & 0xFF00;
	sprite->attribute[0] = sprite->attribute[0] | (y/100);
}

void MovePlatform(OAMEntry* sprite, int x, int y)
{
	sprite->attribute[1] = sprite->attribute[1] & 0xFE00;
	sprite->attribute[1] = sprite->attribute[1] | (x);

	sprite->attribute[0] = sprite->attribute[0] & 0xFF00;
	sprite->attribute[0] = sprite->attribute[0] | (y);
	
}

void MoveGas(OAMEntry* sprite)
{
	if(shipGas%3 == 0)
	{
	sprite->attribute[1] = sprite->attribute[1] & 0xFE00;
	sprite->attribute[1] = sprite->attribute[1] | (shipGas)/3+39;

	sprite->attribute[0] = sprite->attribute[0] & 0xFF00;
	sprite->attribute[0] = sprite->attribute[0] | (8);
	}
	
}

void PositionCalculate(void)
{
	dv=(A-shipThrustY);
	shipVy+=dv;
	shipPositionY+=shipVy;


	dv=(shipThrustX);
	shipVx+=dv;
	shipPositionX+=shipVx;
}

void CopyOAM(void)
{
	int i;
	u16* temp;
	temp = (u16*)sprites;
	for(i = 0; i < 128*4; i++)	
	{
		OAM_Mem[i] = temp[i];
	}
}



void BorderDetection( void )
{
	if(shipPositionX >=20800-800)
	{
		shipPositionX =20800-800-1;
		shipVx=0;
		shipVy=0;
	} 
	if(shipPositionX <= 800)
	{
		shipPositionX = 800-1;
		shipVx=0;
		shipVy=0;
	}
	if(shipPositionY <=800)
	{
		shipPositionY = 800-1;
		shipVx=0;
		shipVy=0;
	}
	if(shipPositionY >=12800-800)
	{
		shipPositionY = 16000-800-1;
		shipVx=0;
		shipVy=0;
	}
}

void CollissionDetection(int ShipPositionX, int ShipPositionY, int PlatformPositionX, int PlatformPositionY  )
{
	int i;
	if(cp[BOTTOM_MIDDLE].x+ShipPositionX/100 >= PlatformPositionX
	&& cp[BOTTOM_MIDDLE].x+ShipPositionX/100 <= PlatformPositionX+cp[BOTTOM_RIGHT].x
	&& cp[BOTTOM_MIDDLE].y+ShipPositionY/100-7 >= PlatformPositionY)
	{
		if(shipVx >= 10 && shipVy >= 10)
		{
			currentState = STATE_LOST;
			memcpy( (u16 *)0x06014000, &crashpricedata, sizeof(enterprisedata) );
		}
		else
		{
			currentState = STATE_WON;
		}
	}
	else if(cp[TOP_RIGHT].x+ShipPositionX/100 >= PlatformPositionX
		  && cp[TOP_RIGHT].x+ShipPositionX/100 <= PlatformPositionX+32
		  && cp[TOP_RIGHT].y+ShipPositionY/100 >=PlatformPositionY
		  && cp[TOP_RIGHT].y+ShipPositionY/100 <=PlatformPositionY+64
			)
	{
		currentState = STATE_LOST;
		memcpy( (u16 *)0x06014000, &crashpricedata, sizeof(enterprisedata) );
	}
	else if( cp[TOP_RIGHT].x+ShipPositionX/100 >= PlatformPositionX
		  &&cp[TOP_LEFT].x+ShipPositionX/100 <= PlatformPositionX+32
		  && cp[TOP_LEFT].y+ShipPositionY/100 >=PlatformPositionY
		  && cp[TOP_LEFT].y+ShipPositionY/100 <=PlatformPositionY+64
			)
	{
		currentState = STATE_LOST;
		memcpy( (u16 *)0x06014000, &crashpricedata, sizeof(enterprisedata) );
	}

	
	
}

void checkGas(void)
{
	if(shipGas >= 300)
	{
		currentState = STATE_TANK_EMPTY;
	}

}

